package com.flower8.sysconfig.config;

import com.flower8.dto.ResponseInfo;
import com.flower8.model.SysAdmin;
import com.flower8.model.SysMenu;
import com.flower8.service.SysAdminService;
import com.flower8.service.SysLogService;
import com.flower8.service.SysMenuService;
import com.flower8.sysconfig.constants.UserConstants;
import com.flower8.sysconfig.exception.BJHAuthenticationException;
import com.flower8.utils.SpringUtil;
import com.flower8.utils.UserUtil;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * shiro拦截
 */
public class MyShiroRealm extends AuthorizingRealm {
	
	private static final Logger log = LoggerFactory.getLogger("adminLogger");

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;

		String username = usernamePasswordToken.getUsername();
		SysAdminService userService = SpringUtil.getBean(SysAdminService.class);
		SysAdmin user = userService.getUser(username);
		if (user == null) {
			ResponseInfo responseInfo = new ResponseInfo();
			responseInfo.setError(true);
			responseInfo.setField("userName");
			responseInfo.setMessage("用户名不正确");
			throw new BJHAuthenticationException(responseInfo);
		}

		if (!user.getPassword().equals(userService.passwordEncoder(new String(usernamePasswordToken.getPassword()), user.getSalt()))) {
			ResponseInfo responseInfo = new ResponseInfo();
			responseInfo.setError(true);
			responseInfo.setField("password");
			responseInfo.setMessage("密码不正确");
			throw new BJHAuthenticationException(responseInfo);
		}

		if (user.getStatus() != UserConstants.STATUS_ON) {
			ResponseInfo responseInfo = new ResponseInfo();
			responseInfo.setError(true);
			responseInfo.setField("userName");
			responseInfo.setMessage("该账号为冻结状态，请联系管理员");
			throw new BJHAuthenticationException(responseInfo);
		}

		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(),
				ByteSource.Util.bytes(user.getSalt()), getName());

		UserUtil.setUserSession(user);
		SpringUtil.getBean(SysLogService.class).save(user.getId(), "系统登录", user.getAccount()+"登录系统");

		return authenticationInfo;
	}

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		log.debug("权限配置");

		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		SysAdmin user = UserUtil.getCurrentUser();
//		List<Role> roles = SpringUtil.getBean(RoleDao.class).listByUserId(user.getId());
//		Set<String> roleNames = roles.stream().map(Role::getName).collect(Collectors.toSet());
//		authorizationInfo.setRoles(roleNames);
		List<SysMenu> permissionList = SpringUtil.getBean(SysMenuService.class).getListByUser(user.getPermission());
		UserUtil.setPermissionSession(permissionList);
		Set<String> permissions = permissionList.stream().filter(p -> !StringUtils.isEmpty(p.getName()))
				.map(SysMenu::getName).collect(Collectors.toSet());
		authorizationInfo.setStringPermissions(permissions);


		return authorizationInfo;
	}

	/**
	 * 重写缓存key，否则集群下session共享时，会重复执行doGetAuthorizationInfo权限配置
	 */
	@Override
	protected Object getAuthorizationCacheKey(PrincipalCollection principals) {
		SimplePrincipalCollection principalCollection = (SimplePrincipalCollection) principals;
		Object object = principalCollection.getPrimaryPrincipal();

		if (object instanceof SysAdmin) {
			SysAdmin user = (SysAdmin) object;

			return "authorization:cache:key:users:" + user.getId();
		}

		return super.getAuthorizationCacheKey(principals);
	}

}
